#include "../include/uart.h"
#include "../include/log.h"
#include"../include/type.h"
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <stdint.h>//用uint定义的
#include<stdbool.h>
#include <stdlib.h>  // 对于 malloc
int uartfd=-1;
unsigned short crc16;

// 初始化串口设备
int uart_init(int *uartfd){
     struct termios old_cfg;
    if(0>tcgetattr(*uartfd,&old_cfg))
    {  
        con_flag = false;
        LOG_ERR("uart connection error\n");
	    return -1;
    }

    struct termios new_cfg;

    memset(&new_cfg,0x0,sizeof(struct termios));

    //配置为原始模式
    cfmakeraw(&new_cfg);

    //使能接收
    new_cfg.c_cflag |= CREAD;

    //设置波特率
    cfsetspeed(&new_cfg,B115200);

    //设置数据位大小
    new_cfg.c_cflag &= ~CSIZE;
    new_cfg.c_cflag |= CS8;//数据位为8位

    //设置奇偶校验


    //奇校验使能
    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;
    //偶校验使能
    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除 PARODD 标志，配置为偶校验 */
    new_cfg.c_iflag |= INPCK;
    //无校验
    new_cfg.c_cflag &= ~PARENB;
    new_cfg.c_iflag &= ~INPCK;

    //设置停止位
    // 将停止位设置为一个比特
    new_cfg.c_cflag &= ~CSTOPB;
    // 将停止位设置为 2 个比特
    new_cfg.c_cflag |= CSTOPB;

    //设置MIN和TIME的值
    new_cfg.c_cc[VTIME] = 0;
    new_cfg.c_cc[VMIN] = 0;
    
    //调用tcflush（）清空缓冲区
    tcflush(*uartfd, TCIOFLUSH);
    
    //调用tcsetattr()将配置写入设备，使其立即生效
    tcsetattr(*uartfd,TCSANOW,&new_cfg);
    return 0;
}

// 串口重连
int uart_reconnect(int *uartfd)
{
	
	while(*uartfd<0){
        close(*uartfd);
	   *uartfd=open("/dev/myuart",O_RDWR | O_NOCTTY | O_NDELAY);
        if (*uartfd < 0) {
            LOG_ERR("Failed to open UART: %s", strerror(errno));
        }
        sleep(1);
	}
    LOG_ERR("Success to reconnect UART");
	return 0;

}

// 发送数据到 UART
int uart_send_data(const uint8_t* data, size_t length)
{
	int bytes_written=write(uartfd,data,length);
	if(bytes_written<0){
		LOG_ERR("Failed to send data via UART");
	}else {
        LOG_DBG("Sent %d bytes via UART", bytes_written);
    }
	return bytes_written;
}

//读取UART数据
int uart_read_data(uint8_t*buffer,size_t length)//size_t 是一种无符号整数类型（即不带符号位），因此它只能表示非负数。其取值范围是 0 到最大正整数值，具体的取值范围取决于系统架构（32位或64位）
{
	int bytes_read=read(uartfd,buffer,length);
	if(bytes_read<0){
		LOG_ERR("Failed to read data from UART");
		  } else {
        LOG_DBG("Read %d bytes from UART", bytes_read);
	}
	return bytes_read;
}

uint16_t calculate_crc16(const uint8_t* data, size_t length)//size_t 的大小是根据系统架构自动调整的（例如在 32 位系统上是 4 字节，在 64 位系统上是 8 字节）
{
	
	uint16_t uCRC = 0xffff;//CRC寄存器
	
	for(uint8_t num=0;num<length;num++){
		uCRC = (*data++)^uCRC;//把数据与16位的CRC寄存器的低8位相异或，结果存放于CRC寄存器。
		for(uint8_t x=0;x<8;x++){	//循环8次
			if(uCRC&0x0001){	//判断最低位为：“1”
				uCRC = uCRC>>1;	//先右移
				uCRC = uCRC^0xA001;	//再与0xA001异或
			}else{	//判断最低位为：“0”
				uCRC = uCRC>>1;	//右移
			}
		}
	}
	LOG_DBG("CRC16 calculated: 0x%04X", uCRC);
	return uCRC;//返回CRC校验值
}

//发送带有CRC校验的数据
void uart_send_command(void* cmd,size_t cmd_size)
{
    
  // 创建一个本地缓冲区
    uint8_t* cmd_bytes = (uint8_t*)malloc(cmd_size);
    if (!cmd_bytes) {
        LOG_ERR("Failed to allocate memory for command buffer");
        return;
    }

    // 拷贝原始命令数据
    memcpy(cmd_bytes, cmd, cmd_size - 2);

    // 计算 CRC 校验码
    uint16_t crc16 = calculate_crc16((uint8_t*)cmd, cmd_size - 2);  // cmd_size - 2 表示不包括最后两个字节

    // 将 CRC 校验码写入 cmd_bytes 的最后两个字节
    cmd_bytes[cmd_size - 2] = (uint8_t)(crc16 & 0xFF);       // crc16 低字节
    cmd_bytes[cmd_size - 1] = (uint8_t)((crc16 >> 8) & 0xFF); // crc16 高字节

    LOG_DBG("CRC attached to command: 0x%02X 0x%02X", cmd_bytes[cmd_size - 2], cmd_bytes[cmd_size - 1]);

    // 通过 UART 发送带有 CRC 校验的命令
    uart_send_data(cmd_bytes, cmd_size);

    // 释放分配的内存
    free(cmd_bytes);

}